/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved.
 *
 */

import { FileSet, TaskInputValue } from '@ohos/hvigor';
import fse from 'fs-extra';

import { OhosLogger } from '../utils/log/ohos-logger.js';

import { TaskNames } from './common/task-names.js';
import { TargetTaskService } from './service/target-task-service.js';
import { OhosHapTask } from './task/ohos-hap-task.js';
import TASK = TaskNames.Task;
import { PagesJsonOption } from '../options/configure/pages-json-option.js';
import PageObj = PagesJsonOption.PageObj;
import { ModuleJson } from '../options/configure/module-json-options.js';
import ModuleOptObj = ModuleJson.ModuleOptObj;
import { TargetSourceSetModel } from '../model/source-set/source-set-model.js';
import { resModelLoader } from '../utils/loader/file/res-model-loader.js';

/**
 * 预览模式下，Stage模型在编译预览代码前更新前置任务生成的module.json和main_pages.json文件
 *
 * @since 2023/2/13
 */
export class PreviewUpdateAssets extends OhosHapTask {
  logger: OhosLogger = OhosLogger.getLogger(PreviewUpdateAssets.name);
  private readonly buildConfigPath: string;
  private paths: string[];
  private contents: string[];

  constructor(taskService: TargetTaskService) {
    super(taskService, TASK.PREVIEW_UPDATE_ASSETS);
    this.paths = [];
    this.contents = [];
    this.buildConfigPath = this.pathInfo.getBuildConfigPath(true);
  }

  declareInputs(): Map<string, TaskInputValue> {
    const inputs = new Map<string, TaskInputValue>();
    if (fse.existsSync(this.buildConfigPath)) {
      // 用文件内容作为增量条件匹配更精确
      const buildConfigJson: any = fse.readJsonSync(this.buildConfigPath);
      if (buildConfigJson.port) {
        delete buildConfigJson.port;
      }
      inputs.set('previewBuildConfigJson', JSON.stringify(buildConfigJson));
    }
    return inputs;
  }

  declareOutputFiles(): FileSet {
    if (fse.existsSync(this.buildConfigPath)) {
      const compileConfig = fse.readJsonSync(this.buildConfigPath);
      const stageRouterConfig = compileConfig.stageRouterConfig;
      if (!stageRouterConfig) {
        return new FileSet();
      }
      this.paths = stageRouterConfig.paths;
      this.contents = stageRouterConfig.contents;
      if (this.paths.length !== this.contents.length) {
        this.logger._buildError("The number of 'paths' doesn't match that of 'contents'.")._file(this.buildConfigPath)._printErrorAndExit();
      }
    } else {
      this.logger.debug(`Build config file not found: ${this.buildConfigPath}`);
    }
    return new FileSet().addEntries(this.paths, { isDirectory: false });
  }

  protected doTaskAction(): void {
    const moduleSourceSetModel = this.targetData.getModuleSourceSetModel() as TargetSourceSetModel;
    const moduleJsonPath = moduleSourceSetModel.getModuleTargetRes().getJsonPath();
    const moduleJsonObj: ModuleOptObj = resModelLoader.getModuleJson(moduleJsonPath);
    const pages = moduleJsonObj.module.pages;
    if (pages) {
      const pageFileName = pages.slice(pages.indexOf(':') + 1);
      this.resolveRouterConfig(this.paths, this.contents, `${pageFileName}.json`);
    } else {
      this.resolveRouterConfig(this.paths, this.contents, 'main_pages.json');
    }
  }

  /**
   * 解析预览传入的页面路由配置
   *
   * @param routerConfigPaths .preview/config/buildConfig.json/stageRouterConfig.paths
   * @param routerConfigContents .preview/config/buildConfig.json/stageRouterConfig.contents
   * @param pagesFileName pagesFileName
   * @private
   */
  private resolveRouterConfig(routerConfigPaths: string[], routerConfigContents: string[], pagesFileName: string) {
    for (let i = 0; i < routerConfigPaths.length; i++) {
      const filePath = routerConfigPaths[i];
      const fileContent = routerConfigContents[i];
      if (filePath.endsWith('module.json')) {
        this.writeModuleJson(filePath, fileContent);
      } else if (filePath.endsWith(pagesFileName)) {
        this.writeMainPages(filePath, fileContent);
      }
    }
  }

  /**
   * 更新前置任务生成的module.json文件
   *
   * @param filePath 文件路径
   * @param fileContent 文件内容
   * @protected
   */
  private writeModuleJson(filePath: string, fileContent: string) {
    if (!this.moduleModel.isHarModule()) {
      return;
    }
    if (fse.existsSync(filePath)) {
      const newContent = JSON.parse(fileContent);
      const moduleInfo = fse.readJsonSync(filePath);
      if (moduleInfo.app) {
        newContent.app = moduleInfo.app;
      }
      if (newContent.module) {
        newContent.module.compileMode = this.targetCompileMode;
        newContent.module.packageName = this.packageJsonObj.name;
      }
      fse.writeJSONSync(filePath, newContent);
    } else {
      fse.ensureFileSync(filePath);
      fse.writeFileSync(filePath, fileContent);
    }
  }

  /**
   * 更新前置任务生成的main_pages.json文件
   *
   * @param filePath 文件路径
   * @param fileContent 文件内容
   * @protected
   */
  private writeMainPages(filePath: string, fileContent: string) {
    let pagesJson: PageObj;
    if (fse.existsSync(filePath)) {
      pagesJson = fse.readJsonSync(filePath);
    } else {
      fse.ensureFileSync(filePath);
      pagesJson = {
        src: [],
      };
    }
    const previewConfigContent = JSON.parse(fileContent);

    // .preview/config/buildConfig.json中content的src替换pages.json的src
    pagesJson.src = previewConfigContent.src;
    fse.writeJSONSync(filePath, pagesJson);
  }

  initTaskDepends(): void {
    this.dependsOnHook('buildPreviewerResource');
  }
}
